#pragma once

#include <linux/major.h>
#include <linux/sched.h>

#define NR_BLK_DEV 7

#define NR_REQUEST 32

struct request {
    int dev; /* -1 if no request */
    int cmd; /* READ or WRITE */
    int errors;
    unsigned long sector;
    unsigned long nr_sectors;
    char *buffer;
    struct buffer_head *bh;
    struct request *next;
};

#define IN_ORDER(s1, s2) \
    ((s1)->cmd < (s2)->cmd || ((s1)->cmd == (s2)->cmd && \
                               ((s1)->dev < (s2)->dev || ((s1)->dev == (s2)->dev && \
                                                          (s1)->sector < (s2)->sector))))

struct blk_dev_struct {
    void (*request_fn)(void);
    struct request *current_request;
};

extern struct blk_dev_struct blk_dev[NR_BLK_DEV];
extern struct request request[NR_REQUEST];
extern struct wait_queue *wait_for_request;

#ifdef MAJOR_NR

#if (MAJOR_NR == HD_MAJOR)
#define DEVICE_NAME    "harddisk"
#define DEVICE_INTR    do_hd
#define DEVICE_REQUEST do_hd_request
#endif

#define REQUEST (blk_dev[MAJOR_NR].current_request)
#define REQUEST_DEV (REQUEST->dev)

#ifdef DEVICE_INTR
void (*DEVICE_INTR)(void) = NULL;
#endif
void(DEVICE_REQUEST)(void);

static inline void end_request() {
    wake_up(&wait_for_request);
    REQUEST->dev = -1;
    REQUEST = REQUEST->next;
}

#endif
